
from datetime import datetime, timedelta
from typing import Union

from fastapi import APIRouter, Depends, HTTPException, status, Form, Request
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from jose import JWTError, jwt

import crud, schemas, models
from database import get_db, get_casbin_e
from schemas import Token, TokenData
from utils import verify_password, APP_TOKEN_CONFIG, oauth2_scheme, get_username_by_token, get_password_hash, verify_enforce, update_array
from api.api_v1.tools.json_resonse import sucessResonse, errorResponse
from objtyping import to_primitive

user_router = router = APIRouter(
    prefix="/v1",
    tags=["User_v1"],
    responses={404: {"description": "Not found"}},  # 请求异常返回数据
)

no_permission = HTTPException(
    status_code=status.HTTP_403_FORBIDDEN,
    detail="您没有该权限！",
    headers={"WWW-Authenticate": "Bearer"},
)

def return_rule(obj, act):
    """
    返回一个验证权限的规则，包括obj、act。
    :param obj:
    :param act:
    :return:
    """
    return schemas.Casbin_rule(obj=obj, act=act)

######################################
# User相关的api接口
######################################

@router.post('/user/create_user')
async def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    # 注册用户名称不能与用户组的role_key重复。
    role = crud.get_role_by_role_key(db, user.username)
    if role:
        return errorResponse(data="注册用户名称不能与用户组的role_key重复")
    return sucessResonse(data = crud.create_user(db, user.username, user.password, user.sex, user.email, user.remark)) 


@router.get("/user/me", response_model=schemas.User)
async def read_users_me(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    """
    返回当前用户的资料
    """
    username = get_username_by_token(token)
    user = crud.get_user_by_username(db, username)
    return sucessResonse(data=to_primitive(user))


@router.get('/user/user_by_id', response_model=schemas.User)
async def get_user_by_id(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db), user_id: int = 0):
    """
    获取指定id用户的资料
    :param token:
    :param db:
    :param user_id:
    :return: schemas.User
    """
    if verify_enforce(token, return_rule('User', 'read')):
        return crud.get_user_by_id(db, user_id)
    else:
        raise no_permission


@router.get('/user/get_users', response_model=schemas.Users)
async def get_users(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db), skip: int = 0, limit: int = 10, keyword: str = ''):
    users = schemas.Users(users=crud.get_users(db, (skip -1 ) * limit, limit, keyword), count=crud.get_users_count_by_keyword(db, keyword))
    return sucessResonse(data = to_primitive(users))


@router.get('/user/active_change')
async def user_active_change(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db), user_id: int = 0):
    """
    修改用户锁定
    :param token:
    :param db:
    :param user_id:
    :return:
    """
    if verify_enforce(token, return_rule('User', 'update')):
        return crud.active_change(db, user_id)
    else:
        raise no_permission


@router.get('/user/delete_user')
async def delete_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db), user_id: int = 0):
    """
    删除用户
    :param token:
    :param db:
    :param user_id:
    :return:
    """
    if verify_enforce(token, return_rule('User', 'delete')):
        return sucessResonse(data= to_primitive(crud.delete_user_by_id(db, user_id)))
    else:
        raise no_permission


@router.post('/user/update_user')
async def update_user(user: schemas.UserUpdate, token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    """
    修改用户资料
    :param user:
    :param token:
    :param db:
    :return:
    """
    if verify_enforce(token, return_rule('User', 'update')):
        u = crud.get_user_by_id(db, user.id)
        # 修改用户名称不能与用户组的role_key重复。
        role = crud.get_role_by_role_key(db, user.username)
        if role:
            return errorResponse(data = '修改用户名称不能与用户组的role_key重复')
        u.username = user.username
        u.email = user.email
        u.sex = user.sex
        u.remark = user.remark
        u.avatar = user.avatar
        if user.password != '':
            hashed_password = get_password_hash(user.password)
            u.hashed_password = hashed_password
        try:
            db.commit()
            return sucessResonse(data = True)
        except:
            return errorResponse(data = False)
    else:
        raise no_permission


@router.post('/user/update_me')
async def update_me(user: schemas.UserUpdate, token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    """
    修改用户资料
    :param user:
    :param token:
    :param db:
    :return:
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_400_BAD_REQUEST,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    username = get_username_by_token(token)
    me = crud.get_user_by_username(db,username)
    if user.user_id == me.id:
        u = crud.get_user_by_id(db, user.user_id)
        u.username = user.username
        u.email = user.email
        u.sex = user.sex
        u.remark = user.remark
        u.avatar = user.avatar
        if user.password != '':
            hashed_password = get_password_hash(user.password)
            u.hashed_password = hashed_password
        try:
            db.commit()
            return True
        except:
            raise credentials_exception
    else:
        raise credentials_exception


@router.post('/user/change_user_role')
async def change_user_role(data: schemas.ChangeUserRole, token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    """
    修改用户拥有的用户组
    :param data:
    :param token:
    :param db:
    :return:
    """
    if verify_enforce(token, return_rule('User', 'update')):
        # 将用户组名称改成role_key
        role_keys = []
        for name in data.names:
            role = crud.get_role_by_name(db, name)
            role_keys.append(role.role_key)
        return crud.change_user_role(db, data.user_id, role_keys)
    else:
        raise no_permission


@router.get('/user/get_user_role')
async def get_user_role(user_id: int, token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    """
    获取用户所拥有的用户组
    :param user_id:
    :param token:
    :param db:
    :return:
    """

    if verify_enforce(token, return_rule('User', 'read')):
        user = crud.get_user_by_id(db, user_id)
        roles = crud.get_roles(db)
        options = []  # 所有的权限组名称
        for role in roles:
            options.append(role.name)

        checkeds = []  # 当前用户所拥有的用户组
        crs = crud.get_casbin_rules_by_username(db, user.username)
        for cr in crs:
            role = crud.get_role_by_role_key(db, cr.v1)
            checkeds.append(role.name)
        return {'options': options, 'checkeds': checkeds}
    else:
        raise no_permission

@router.get('/route/info')
async def get_user_router(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    """
    获取用户路由元数据
    :param token:
    :param db:
    :return:
    """
    responseData = [
        {
            'name': "remote",
            'path': "/remote",
            'component': "common-page",
            'meta': { 'auth': True, 'menu': { 'title': "router.remote", 'icon': "Cloudy" } },
            'children': [
              {
                'name': "article_remote",
                'path': "article_remote",
                'component': "/design/ArticlePage.vue",
                'meta': { 'menu': { 'title': "router.article_remote" } }
              }
            ]
          }
    ]
    if verify_enforce(token, return_rule('User', 'read')):
        return sucessResonse(data=to_primitive(responseData))
    else:
        raise no_permission
